#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>

int new_socket(const char *path)
{
    int rv = -1;
    int socket_fd = -1;
    struct sockaddr_un self_util;

    if(path == NULL)
    {
        return -1;
    }

    socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(socket_fd < 0)
    {
        printf("creat socket failed, errno(%d), desc(%s)", errno, strerror(errno));
        return -1;
    }

    bzero(&self_util, sizeof(struct sockaddr_un));
    self_util.sun_family = AF_UNIX;
    strcpy(self_util.sun_path, path);

    unlink(self_util.sun_path);
    rv = bind(socket_fd, (struct sockaddr *) &self_util, sizeof(struct sockaddr_un));
    if (rv)
    {
        printf("bind failed, errno(%d), desc(%s)\n", errno, strerror(errno));
        close(socket_fd);
        return -1;
    }

    return socket_fd;
}

typedef struct ctx_t__ {
    char exit;
} ctx_t;

static struct un_info_ {
    int     index;
    char    *path_name;
} g_un_info[] = {
    {0, "/data/socket/triffic_sock" },
    {1, "/data/socket/obtain_proto_sock" },
    {2, "/data/socket/event_sock"},
    {3, "/data/socket/allow_list_sock"},
    {4, "/data/socket/self_socket"},
    {5, "/data/socket/industry_sock"},
    {6, "/data/socket/white_list_warning_sock"},
    {7, "/data/socket/custom_protocol_warning_sock"},
    {8, "/data/socket/session_statistic_sock"},
    {9, "/data/socket/engine_update_configuration_sock"},
};

static ctx_t g_context = {0};

void *data_handler(void *arg)
{
    struct un_info_ *l_un_info = (struct un_info_ *)arg;
    int s_fd = -1;
    ssize_t r;
    char buf[1024] = {0};

    s_fd = new_socket(l_un_info->path_name);
    if (s_fd <= 0)
    {
        printf("new_socket failed, s_fd:%d\n", s_fd);
        return NULL;
    }

    while (!g_context.exit)
    {
        r = recv(s_fd, buf, sizeof(buf) / sizeof(char), 0);
        if (r > 0)
        {
            printf("[RX] index:[%d] size:[%ld], content:[%s]\n", l_un_info->index, r, buf);
        }
        else if (r == 0)
        {
            printf("r == 0, error(%d), desc(%s)\n", errno, strerror(errno));
            usleep(300);
        }
        else
        {
            printf("r < 0, fd:(%d) error(%d), desc(%s)\n", s_fd, errno, strerror(errno));
            usleep(300);
        }
        memset(buf, 0, sizeof(buf));
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    int i = 0;
    int cnt = sizeof(g_un_info) / sizeof(g_un_info[0]);

    pthread_t *tids = calloc(1, sizeof(int) * cnt);

    for (i = 0; i < cnt; i++) {
        pthread_create(&tids[i], NULL, data_handler, (void *)&g_un_info[i]);
    }

    for (i = 0; i < cnt; i++) {
        pthread_join(tids[i], NULL);
    }

    free(tids); tids = NULL;

    return 0;
}
